#include "Socket.hpp"
#include "log.hpp"
#include <sys/select.h>
#define maxselectsize 1024
class SelectSever
{
private:
    void accepter()//接收逻辑是要将新的文件描述符添加到读文件描述符集里面
    {
        string ip;
        uint16_t port;
        int sock = Sock::Accept(_listensocket,&ip,&port);
        logMessage(NORMAL,"新连接到来，客户端ip: %s,端口: %d\n",ip.c_str(),port);
        int pos = 0;
        for(pos = 0;pos<maxselectsize;pos++)
        {
            if(selectbuffer[pos] == -1) break;
        }
        if(pos == maxselectsize) close(sock);
        else selectbuffer[pos] = sock;
    }
    void recever(int pos)//普通读取逻辑
    {
        char buffer[1024];
        int s = recv(selectbuffer[pos],buffer,sizeof(buffer) - 1,0);
        if(s == 0)
        {
            logMessage(NORMAL,"客户端关闭\n");
            close(selectbuffer[pos]);
            selectbuffer[pos] = -1;
        }
        else if(s < 0)
        {
            logMessage(WARNING,"读取错误，我要关闭你了\n");
            close(selectbuffer[pos]);
            selectbuffer[pos] = -1;
        }
        else
        {
            buffer[s] = 0;
            //cout<<"echo : "<<buffer<<endl;
            logMessage(NORMAL,"cilent say: %s\n",buffer);
        }
    }
public:
    SelectSever(uint16_t port)
        : _port(port)
    {
        //初始化这个select关心的数组
        for(int i = 0;i<maxselectsize;i++)
        {
            selectbuffer[i] = -1;
        }
        _listensocket = Sock::Socket();
        Sock::Bind(_listensocket, _port);
        Sock::Listen(_listensocket);
        selectbuffer[0] = _listensocket;
        logMessage(DEBUG, "服务器初始化成功，开始监听\n");

    }

    void start()
    {
        fd_set rfds;
        while (1)//每次进来都要重新初始化rfds
        {
            struct timeval tv = {0, 0};
            FD_ZERO(&rfds);
            int maxfd = _listensocket;
            for(int i = 0;i<maxselectsize;i++)
            {
                if(selectbuffer[i] == -1) continue;
                //走到这里说明一定是一个合法的文件描述符 合法的文件描述符就要添加到rfds里面去
                FD_SET(selectbuffer[i], &rfds);
                if(maxfd < selectbuffer[i]) maxfd = selectbuffer[i];//如果maxfd小于当前fd 则更新
            }
            int rs = select(maxfd + 1, &rfds, nullptr, nullptr, nullptr);
            switch (rs)
            {
            case 0:
                logMessage(DEBUG, "waiting for data reday···\n");
                continue;
            case -1:
                logMessage(WARNING, "select error %d : %s\n", errno, strerror(errno));
                continue;
            default:
                SelectHandler(&rfds);
                break;
            }
        }
    }
    ~SelectSever()
    {
        if(_listensocket > 0) close(_listensocket);
    }
private:
    void SelectHandler(fd_set* prfds)
    {

        for(int i = 0;i<maxselectsize;i++)
        {
            //首先要遍历数组看看每个fd是否被置位
            if(selectbuffer[i] == -1) continue;
            //走到这里说明一定是一个合法的fd，但也要继续判断到底是一个连接事件 还是普通事件
            if(FD_ISSET(selectbuffer[i],prfds))
            {
                if(i == 0)//说明这个是连接事件，连接事件就要进行连接的逻辑
                accepter();
                else//这里之后才是普通事件
                recever(i);
            }
        }
        // if(FD_ISSET(_listensocket,rfds))
        // {
        //     string clientip;
        //     uint16_t clientport;
        //     int sock = Sock::Accept(_listensocket,&clientip,&clientport);
        //     if(sock < 0)
        //     {
        //         logMessage(WARNING, "accept error %d : %s\n", errno, strerror(errno));
        //         return;
        //     }
        //     logMessage(DEBUG,"获取到新连接: [%s : %d]\n",clientip.c_str(),clientport);
        //     //cout<<"获取到新连接,ip : "<<clientip.c_str()<<"port : "<<clientport<<endl;
        // }
    }

private:
    int _listensocket;
    uint16_t _port;
    int selectbuffer[maxselectsize];
};